package vip.xiaonuo.biz.modular.event.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.BetweenFormatter;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vip.xiaonuo.biz.modular.event.entity.BizEvent;
import vip.xiaonuo.biz.modular.event.entity.BizEventConfig;
import vip.xiaonuo.biz.modular.event.mapper.BizEventConfigMapper;
import vip.xiaonuo.biz.modular.event.mapper.BizEventMapper;
import vip.xiaonuo.biz.modular.event.service.BizEventGoodsLedgerService;
import vip.xiaonuo.biz.modular.event.service.BizEventReplaceService;
import vip.xiaonuo.biz.modular.goods.entity.BizGoods;
import vip.xiaonuo.biz.modular.goods.entity.BizGoodsLedger;
import vip.xiaonuo.biz.modular.goods.mapper.BizGoodsLedgerMapper;
import vip.xiaonuo.biz.modular.goods.mapper.BizGoodsMapper;
import vip.xiaonuo.common.util.AliyunSmsUtil;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 墨塵
 * @since 2023/2/21
 */
@Service
@Transactional
public class BizEventGoodsLedgerServiceImpl implements BizEventGoodsLedgerService {

    @Resource
    private BizGoodsLedgerMapper bizGoodsLedgerMapper;

    @Resource
    private BizGoodsMapper bizGoodsMapper;

    @Resource
    private BizEventMapper bizEventMapper;

    @Resource
    private BizEventConfigMapper bizEventConfigMapper;

    @Resource
    private BizEventReplaceService bizEventReplaceService;

    @Override
    public void handleGoodsLend() {
        //获取物品借出未归还列表
        List<BizGoodsLedger> unreturnedList = bizGoodsLedgerMapper.getUnreturnedList();
        for (BizGoodsLedger item : unreturnedList) {
            //获取物品信息
            BizGoods goods = bizGoodsMapper.selectById(item.getGoodsId());
            if (goods.getState() == 0) {
                //报废物品跳过
                continue;
            }
            //预警间隔
            Integer alertInterval = goods.getAlertInterval() != null ? goods.getAlertInterval() : 1;
            //预警间隔单位
            Integer alertIntervalUnit = goods.getAlertIntervalUnit() != null ? goods.getAlertIntervalUnit() : 1;
            //预警次数
            Integer alertMaxNum = goods.getAlertMaxNum() != null ? goods.getAlertMaxNum() : 1;
            //约定归还时间和当前时间间隔（秒）
            long betweenSec = DateUtil.between(item.getReturnTime(), DateUtil.date(), DateUnit.SECOND, false);

            if (betweenSec > 0) {
                //未设置不生成事件
                if (goods.getMaxLimitLeave() != null) {
                    //获取提醒次数
                    List<BizEvent> eventList = bizEventMapper.getListForOverdueReturn(goods.getId(), item.getId());
                    if (eventList.size() == 0) {
                        //生成事件(第一次)
                        this.addOverdueReturnRecord(item, goods);
                    } else {
                        if (eventList.size() < alertMaxNum) {
                            //判断与上一次间隔时间
                            if (DateUtil.between(eventList.get(0).getEventTime(), DateUtil.date(), getBetweenUtil(alertIntervalUnit), false) > alertInterval) {
                                //生成事件
                                this.addOverdueReturnRecord(item, goods);
                            }
                        }
                    }
                }
            } else {
                //即将超期
                if (goods.getImpendPrompt() != null) {
                    Integer impendPormptUnit = goods.getImpendPromptUnit() != null ? goods.getImpendPromptUnit() : 1;
                    //获取提醒次数
                    List<BizEvent> eventList = bizEventMapper.getListForNearOverdueReturn(goods.getId(), item.getId());
                    //到期前间隔
                    long betweenReturn = DateUtil.between(DateUtil.date(), item.getReturnTime(), getBetweenUtil(impendPormptUnit), false);
                    if (betweenReturn < goods.getImpendPrompt()) {
                        if (eventList.size() == 0) {
                            //生成事件(第一次)
                            this.addNaerOverdueReturnRecord(item, goods);
                        } else {
                            if (eventList.size() < alertMaxNum) {
                                //判断与上一次间隔时间
                                if (DateUtil.between(eventList.get(0).getEventTime(), DateUtil.date(), getBetweenUtil(impendPormptUnit), false) > alertInterval) {
                                    //生成事件
                                    this.addNaerOverdueReturnRecord(item, goods);
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * 获取间隔单位
     *
     * @param unit
     * @return
     */
    private DateUnit getBetweenUtil(Integer unit) {
        switch (unit) {
            case 1:
                return DateUnit.MINUTE;
            case 2:
                return DateUnit.HOUR;
            case 3:
                return DateUnit.DAY;
            default:
                return DateUnit.MINUTE;
        }
    }

    /**
     * 超期记录
     *
     * @param goodsLedger
     * @param goods
     */
    private void addOverdueReturnRecord(BizGoodsLedger goodsLedger, BizGoods goods) {
        //查询对应配置
        BizEventConfig eventConfig = bizEventConfigMapper.selectById("19");
        //当前时间
        DateTime now = DateUtil.date();
        //事件描述
        String eventDesc = eventConfig.getEventDesc();
        String goodsName = bizEventReplaceService.getGoodsNameForEntity(goods);
        eventDesc = eventDesc.replace("{{goods}}", goodsName);
        eventDesc = eventDesc.replace("{{ret-time}}", DateUtil.formatDateTime(goodsLedger.getReturnTime()));
        //超期时间
        String ovdStr = DateUtil.formatBetween(goodsLedger.getReturnTime(), now, BetweenFormatter.Level.SECOND);
        eventDesc = eventDesc.replace("{{ovd-hour}}", ovdStr);
        eventDesc = eventDesc.replace("{{time}}", DateUtil.formatDateTime(DateUtil.date()));
        //组合实体类
        BizEvent event = BeanUtil.toBean(eventConfig, BizEvent.class);
        event.setEventConfigId(eventConfig.getId());
        event.setEventTime(DateUtil.date());
        event.setEventDesc(eventDesc);
        event.setEventUserId(goodsLedger.getDeliveryUserId());
        event.setEventAction(9);
        event.setGoodsId(goods.getId());
        event.setGoodsLedgerId(goodsLedger.getId());
        event.setCabinetGroupId(goods.getBioCabinetGroupId());
        event.setCabinetId(goods.getBioCabinetId());
        event.setCabinetDoorId(goods.getBioCabinetDoorId());
        event.setEventUserId(goodsLedger.getDeliveryUserId());
        bizEventReplaceService.clearBizEvent(event);
        //类目切换
        bizEventReplaceService.itemSwitch(event, goods.getGoodsType());
        bizEventMapper.insert(event);

        //【邮件+短信】借用人，柜门管理员
        bizEventReplaceService.sendEmailForUser(goodsLedger.getDeliveryUserId(), event);
        bizEventReplaceService.sendEmailForDoorAdmin(event);
        Map<String, String> content = new HashMap<>();
        content.put("goods", goodsName);
        content.put("rettime", DateUtil.formatDateTime(goodsLedger.getReturnTime()));
        content.put("ovdhour", ovdStr);
        content.put("time", DateUtil.formatDateTime(DateUtil.date()));
        bizEventReplaceService.sendSmsForUser(goodsLedger.getDeliveryUserId(), event, AliyunSmsUtil.OVERDUE_NON_RETURN, content);
        bizEventReplaceService.sendSmsForDoorAdmin(event, AliyunSmsUtil.OVERDUE_NON_RETURN, content);
    }

    /**
     * 临近超期记录
     *
     * @param goodsLedger
     * @param goods
     */
    private void addNaerOverdueReturnRecord(BizGoodsLedger goodsLedger, BizGoods goods) {
        //查询对应配置
        BizEventConfig eventConfig = bizEventConfigMapper.selectById("21");
        //当前时间
        DateTime now = DateUtil.date();
        //事件描述
        String eventDesc = eventConfig.getEventDesc();
        eventDesc = eventDesc.replace("{{goods}}", bizEventReplaceService.getGoodsNameForEntity(goods));
        eventDesc = eventDesc.replace("{{ret-time}}", DateUtil.formatDateTime(goodsLedger.getReturnTime()));
        //超期时间
        String ovdStr = DateUtil.formatBetween(now, goodsLedger.getReturnTime(), BetweenFormatter.Level.SECOND);
        eventDesc = eventDesc.replace("{{remain-hour}}", ovdStr);
        eventDesc = eventDesc.replace("{{time}}", DateUtil.formatDateTime(DateUtil.date()));
        //组合实体类
        BizEvent event = BeanUtil.toBean(eventConfig, BizEvent.class);
        event.setEventConfigId(eventConfig.getId());
        event.setEventTime(DateUtil.date());
        event.setEventDesc(eventDesc);
        event.setEventUserId(goodsLedger.getDeliveryUserId());
        event.setEventAction(9);
        event.setGoodsId(goods.getId());
        event.setGoodsLedgerId(goodsLedger.getId());
        event.setCabinetGroupId(goods.getBioCabinetGroupId());
        event.setCabinetId(goods.getBioCabinetId());
        event.setCabinetDoorId(goods.getBioCabinetDoorId());
        event.setEventUserId(goodsLedger.getDeliveryUserId());
        bizEventReplaceService.clearBizEvent(event);
        //类目切换
        bizEventReplaceService.itemSwitch(event, goods.getGoodsType());
        bizEventMapper.insert(event);

        //【邮件】借用人
        bizEventReplaceService.sendEmailForUser(goodsLedger.getDeliveryUserId(), event);
    }
}
